#include "TestServerSendLoop.h"

#include "Network.h"
#include "Object.h"
#include <conio.h>

using namespace boost::asio::ip;

class Player
{
public:
	Player() {
		_control = NULL;
		_player = NULL;
	}
	Player(udp::endpoint endpoint, ControlMessage *control, PlayerMessage *player): _endpoint(endpoint)
	{
		_control = control;
		_player = player;
	}
	void update()
	{
		_player->positionX = (float)_control->mouseX;
		_player->positionY = (float)_control->mouseY;
		std::cout << "  " << _endpoint << ": position=(" <<
			_player->positionX << ", " <<
			_player->positionY << ")" << std::endl;
		Object::sendMessage(_player);
	}

	udp::endpoint _endpoint;
	ControlMessage *_control;
	PlayerMessage *_player;
};

std::map<unsigned long, Player> playerMap;

class ControlListener: public MessageHandler
{
public:
	virtual void onReceivePlayerMessage(PlayerMessage *receivedMessage, boost::asio::ip::udp::endpoint endpoint) {
		// not needed by server
	}
	virtual void onReceiveItemMessage(ItemMessage *receivedMessage, boost::asio::ip::udp::endpoint endpoint) {
		// not needed by server
	}
	virtual void onReceiveControlMessage(ControlMessage *control, udp::endpoint senderEndpoint)
	{
		// check if this is the first control message from the respective machine
		if (playerMap[control->_id._machine]._control == NULL)
		{
			std::cout << "  new player at: " << senderEndpoint << std::endl;
			PlayerMessage *player = Object::createPlayerMessage(control->_id._machine);
			playerMap[control->_id._machine] = Player(senderEndpoint, control, player);
			Network::addReceiverEndpoint(senderEndpoint);
		}
	}
};


void TestServerSendLoop::run()
{
	int frame = 0;
	ControlListener controlListener;

	Object::init();
	Object::setMessageHandler(&controlListener);
	Object::startReceiving();

	std::cout << "server startet at " << Network::getLocalEndpoint() << std::endl;
	while (!kbhit())
	{
		// handle incoming messages:
		Object::receiveMessage();
		std::cout << "frame " << frame++ << std::endl;
		std::map<unsigned long, Player>::iterator playerIt;
		for (playerIt = playerMap.begin(); playerIt != playerMap.end(); playerIt++)
		{
			playerIt->second.update();
		}
		boost::posix_time::milliseconds waitTime(1000);
		boost::this_thread::sleep(waitTime);
	}
	Object::stopReceiving();

	return;
}
